package com.aizuda.encrypt.util;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.extra.spring.SpringUtil;
import com.aizuda.encrypt.constant.EncryptConstant;
import com.aizuda.encrypt.entity.FieldInfo;
import com.aizuda.encrypt.enums.EncryptType;
import com.aizuda.encrypt.helper.CryptoHelper;
import com.aizuda.encrypt.helper.DecryptToolKit;
import com.aizuda.encrypt.service.TransTableService;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 解密工具类
 *
 * @author nn200433
 * @date 2024-03-26 08:45:22
 */
public class DecryptUtil {

    /**
     * 是否需要解密
     *
     * @param clz clz
     * @return boolean
     * @author nn200433
     */
    public static boolean isNeedDecrypt(Class<?> clz) {
        return getToolKit().isNeedDecrypt(clz);
    }

    /**
     * 获取需要解密的字段
     *
     * @param clz clz
     * @return {@link Map }<{@link Field }, {@link FieldInfo }>
     * @author nn200433
     */
    public static Map<Field, FieldInfo> getDecryptField(Class<?> clz) {
        return getToolKit().getDecryptField(clz);
    }

    /**
     * 获取需要设值的方法
     *
     * @param clz clz
     * @return {@link Map }<{@link Field }, {@link Method }>
     * @author nn200433
     */
    public static Method getInvokSetMethod(Class<?> clz, Field field) {
        return getToolKit().getInvokSetMethod(clz, field);
    }

    /**
     * 解密数据
     *
     * @param type 类型
     * @param key  密钥
     * @param str  要解密的数据
     * @return {@link String }
     * @author nn200433
     */
    public static String decrypt(EncryptType type, String key, String str) {
        final int padPreCount = EncryptConstant.PAD_PRE_COUNT;
        final int length      = str.length();
        Assert.notBlank(str, "解密的字符串必填！");
        Assert.isTrue(length > padPreCount, "解密的字符串长度必须大于{}个字符串。", padPreCount);
        final TransTableService transTable    = CryptoHelper.transTable();
        final SymmetricCrypto   crypto        = CryptoHelper.cryptoHandler(type, key);
        final String            beginIndexHex = transTable.translate(str.substring(0, padPreCount));
        final int               beginIndex    = HexUtil.hexToInt(beginIndexHex);
        final String            encryptZHStr  = str.substring(padPreCount);
        final String            encryptStr    = transTable.translate(encryptZHStr.substring(beginIndex));
        return crypto.decryptStr(encryptStr);
    }

    /**
     * 获取工具包
     *
     * @return {@link DecryptToolKit }
     * @author nn200433
     */
    private static DecryptToolKit getToolKit() {
        return SpringUtil.getBean(DecryptToolKit.class);
    }

}
